//
// Created by ta&to on 2022/9/26.
//

#ifndef HTTPSERVER_HTTP_SOCKET_H
#define HTTPSERVER_HTTP_SOCKET_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include "hash_util.h"

#define HTTPSERVER_OPEN 1 // 启用http 服务

#define NONE 0       /* No events registered. */
#define READABLE 1   /* Fire when descriptor is readable. */
#define WRITABLE 2   /* Fire when descriptor is writable. */

typedef struct http_socket_event_loop_s http_socket_event_loop_t;
typedef struct http_socket_event_handle_s http_socket_event_handle_t;

#if defined(__MINGW32__) || defined(__MINGW64__)
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#if defined(SOCKET_SERVER_POLL)
#include <poll.h>
#elif defined(SOCKET_SERVER_EPOLL)
#include <sys/epoll.h>
#endif
#endif
#ifdef HTTPSERVER_OPEN
#include "http_handler.h"
#endif
#define BUF_SIZE 200

#define HTTP_SOCKET_CLOSE 0b01
#define HTTP_SOCKET_OPEN  0b10

#define HTTP_SOCKET_CLOSE_SERVER 0b01
#define HTTP_SOCKET_CLOSE_CLIENT 0b10

#ifdef SOCKET_SERVER_SELECT
typedef void (*socket_callback_func)(http_socket_event_loop_t *hset, int fd, int n);
#else
typedef void (*socket_callback_func)(http_socket_event_loop_t *hset, int fd);
#endif
#ifdef SOCKET_SERVER_SELECT
struct select_event{
    int events;         // Epoll events 要监听的事件类型
    int fd;             // 要监听连接描述符
};
#endif

struct http_socket_event_handle_s{
    int fd;
    struct sockaddr_in client_addr; // 客户端的地址信息
    socklen_t sin_size;             // 客户端地址长度
    socket_callback_func func_read;
    socket_callback_func func_write;
    int data_len;                   // 缓存长度
    char *data;                     // 缓存数据
};
struct http_global_data_container{
    thread_pool_t *tpt;
    Leader req_maps_header;
    pthread_mutex_t req_maps_header_lock;                           // 请求头锁全局锁 对于请求头容器的相关操作都要加锁
    Leader req_maps_fds;
    pthread_mutex_t req_maps_fds_lock;                              // 文件描述符全局锁 对于文件描述符的全局容器相关操作都要加锁
};
struct http_global_data_event_func_container{
    http_socket_event_handle_t *temp_func_handler;   // 局部数据模板
    Leader func_handler;    // 局部数据
    pthread_mutex_t event_fun_lock;
};
struct http_socket_event_loop_s{
    int maxfd;               // 最大的链接数(数字)
    int max_link;            // 准备就绪队列的最大链接数
    int current_link;        // 当前连接数
    int current_fd;          // 当前套接字
    int socket_fd;           //监听套接字
    char *workpath;          // 项目路径
    struct timeval *tvp;
    log_t *logs;             // 日志
#ifdef HTTPSERVER_OPEN
    struct http_global_data_event_func_container *hgdefc;
    struct http_global_data_container *hgdc; // 用于存放http全局资源
#endif
#ifdef SOCKET_SERVER_SELECT
    fd_set rfds;           // 用于存放需要监控的事件相关事件描述符的标识值 读
    struct select_event *select_ev_fds; // 链接的文件描述符
#endif
#ifdef SOCKET_SERVER_POLL
    struct pollfd *poll_ev_fds;
#endif
#ifdef SOCKET_SERVER_EPOLL
    int epoll_fd; //epoll 自身的文件描述符
    struct epoll_event *epoll_ev_fds; // 准备就绪的文件描述符
#endif
};
typedef struct http_socket_event_loop_s http_socket_event_t;
int CreateHttpSocket(log_t *logt,const in_addr_t listen_addr, int listen_port, int link_num);
int Accept(log_t *logt, int socket_fd, struct sockaddr *saddr, socklen_t *slen);
int putData(log_t *logt, const int socket_fd, char* buf, int len);
int getData(log_t *logt, const int socket_fd, char* buf, int len);
int vgetData(log_t *logt, const int client_fd, char* buf, int len);
int noSgPutData(log_t *logt,const int client_fd, char* buf, int len);
void CloseAll(log_t *logt, int socket_fd, int client_fd);
#endif //HTTPSERVER_HTTP_SOCKET_H
